package shopping

import (
	"time"
	"strconv"
	"strings"
	"wxsdk/miniapp/core"
	"encoding/json"
	"dhfshop/utils/helper"
	"dhfshop/utils/uuid"
	"dhfshop/utils/math"
	"dhfshop/utils/response"
	"dhfshop/models/shopping"
	"dhfshop/models/sale"
	"dhfshop/models/im"
	"dhfshop/models/isv"
	"dhfshop/models/seller"
	"dhfshop/models/member"
	"dhfshop/models/misc"
	"dhfshop/models/consts"
	"dhfshop/controllers/base"
	"dhfshop/service/event"
	"dhfshop/service/redisgo"
	"dhfshop/domain/orders"
	"dhfshop/domain/member"
	"dhfshop/domain/pay"
	"dhfshop/service/nsqcli"
	"github.com/astaxie/beego/validation"
	"github.com/pkg/errors"
	"github.com/looplab/fsm"
	"github.com/astaxie/beego"
	"dhfshop/domain/im"
)

func TradeEventInit() {
	event.KernelBus.Subscribe("E_ORDER_CANCEL",TradeFsm)
	event.KernelBus.Subscribe("E_ORDER_PAYMENT",TradeFsm)
	event.KernelBus.Subscribe("E_ORDER_CONFIRM",TradeFsm)
	event.KernelBus.Subscribe("E_ORDER_DELIVERY",TradeFsm)
	event.KernelBus.Subscribe("E_ORDER_RECEIVE",TradeFsm)
	event.KernelBus.Subscribe("E_ORDER_RATED",TradeFsm)
	event.KernelBus.Subscribe("E_ORDER_SERVICE",TradeFsm)
	event.KernelBus.Subscribe("E_ORDER_REFUND",TradeFsm)
	event.KernelBus.Subscribe("E_ORDER_CLOSE",TradeFsm)
	event.KernelBus.Subscribe("E_ORDER_CONFIRMPAYMENT",TradeFsm)
	//
	event.KernelBus.Subscribe("E_ORDER_CONFIRM",TradeConfirm)    //订单已确认 —>  给买家发送 模板消息
	event.KernelBus.Subscribe("E_ORDER_DELIVERY",TradeDelivery)  //订单已发货 —>  给买家发送 模板消息
	event.KernelBus.Subscribe("E_ORDER_RECEIVE",TradeWaitRated)  //待评价 —>      给买家发送 模板消息
	event.KernelBus.Subscribe("E_ORDER_SERVICE",TradeEnterReturn)
}

func TradeFsm(message string,out *string){
	var msg event.TradeMsg
	if result, err := event.DecodeMsg(message, &msg); err != nil {
	    beego.Debug("result:", result)
		*out = err.Error()
		return
	}
	orders, err := shopping.GetOrderById(msg.OrderId)
	if err != nil {
	    *out = err.Error()
		return
	}
	curState := orders.Status
	fsmEvents, err := event.GetFsmStateByJson(consts.OrderDefaultState)
	if err != nil {
		*out = err.Error()
		return
	}
	if orders.FlowType == 1 {
	    fsmEvents, err = event.GetFsmStateByJson(consts.InStoreConsumeState)
	    if err != nil {
		    *out = err.Error()
		    return
	    }
	}
	if orders.FlowType == 2 {
	    fsmEvents, err = event.GetFsmStateByJson(consts.AnonymousOrderState)
	    if err != nil {
		    *out = err.Error()
		    return
	    }
	}
	orderfsm := fsm.NewFSM(
	  curState,
	  fsmEvents,
	  fsm.Callbacks{},
	)
	err = orderfsm.Event(msg.MsgHeader.EventType)
	if err != nil {
		*out = err.Error()
		return
	}
	nextState := orderfsm.Current()
	m := &shopping.ValueOrder{OrderId: msg.OrderId, Status: nextState}
	if nextState == "S_ORDER_WAIT_CONFIRM" {
		shopping.UpdateOrderPayInfo(m)
	}
	if nextState == "S_ORDER_WAIT_RECEIVE" {
		shopping.UpdateOrderDeliverTime(m)
	}
	if(orders.FlowType == 2)&&(nextState == "S_ORDER_COMPLETED"){
		shopping.UpdateOrderPayInfo(m)
	}
	err = shopping.UpdateOrderStatus(m)
	if err != nil {
	    *out = err.Error()
		return
	}
	return
}

func TradeConfirm(message string, out *string){
	var msg event.TradeMsg
	if result, err := event.DecodeMsg(message, &msg); err != nil {
	    beego.Debug("result:", result)
		*out = err.Error()
		return
	}
	beego.Debug("TradeConfirm:", msg.MsgHeader.EventType, msg.OrderId)
	orderIdStr := strconv.FormatInt(msg.OrderId, 10)
	order, err := shopping.GetOrderById(msg.OrderId)
	if err != nil {
	    beego.Debug("GetOrderById:", err.Error())
	    return
	}
	members, err := member.GetMemberById(order.MemberId)
	if err != nil {
	    beego.Debug("GetMemberById:", err.Error())
		return
	}
	custAccount, err := isv.GetCustAccountByAppId(members.AppId)
	if err != nil {
		beego.Debug("GetCustAccountByAppId:", err.Error())
		return
	}
	templateId, err := imlayer.GetTemplateId(msg.CompanyId,members.AppId,"AT0163")
	if err != nil {
		beego.Debug("GetTemplateId:", err.Error())
		return
	}
	prepayId, err := im.GetFormIdByOpenId(members.OpenID,"order",orderIdStr)
	if err != nil {
		beego.Debug("GetFormIdByOpenId:", err.Error())
		return
	}
	page := "pages/order/detail/index?order_id=" + orderIdStr
	var itemTitleArr []string
	for _, value := range order.Items {
	    itemTitleArr = append(itemTitleArr, value.Title)
	}
	err = imlayer.OrderConfirmTempMsg(custAccount.AccessToken,page,members.OpenID,templateId,prepayId,orderIdStr,strings.Join(itemTitleArr,","))
	if err != nil {
		beego.Debug("OrderConfirmTempMsg:", err.Error())
	}
	timestamp := time.Now().Format("200601021504")
        err = imlayer.OrderNotifyMsg(msg.OrderId,order.Status,timestamp)
        if err != nil {
          beego.Debug("OrderNotifyMsg:", err.Error())
        }
	return
}

func TradeDelivery(message string, out *string){
	var msg event.TradeMsg
	if result, err := event.DecodeMsg(message, &msg); err != nil {
	    beego.Debug("result:", result)
		*out = err.Error()
		return
	}
	orderIdStr := strconv.FormatInt(msg.OrderId, 10)
	beego.Debug("TradeDelivery:", msg.MsgHeader.EventType, msg.OrderId)
	order, err := shopping.GetOrderById(msg.OrderId)
	if err != nil {
	    beego.Debug("GetOrderById:", err.Error())
	    return
	}
	members, err := member.GetMemberById(order.MemberId)
	if err != nil {
	    beego.Debug("GetMemberById:", err.Error())
		return
	}
	custAccount, err := isv.GetCustAccountByAppId(members.AppId)
	if err != nil {
		beego.Debug("GetCustAccountByAppId:", err.Error())
		return
	}
	templateId, err := imlayer.GetTemplateId(msg.CompanyId,members.AppId,"AT0007")
	if err != nil {
		beego.Debug("GetTemplateId:", err.Error())
		return
	}
	prepayId, err := im.GetFormIdByOpenId(members.OpenID,"order",orderIdStr)
	if err != nil {
		beego.Debug("GetFormIdByOpenId:", err.Error())
		return
	}			    
	page := "pages/order/detail/index?order_id=" + orderIdStr
	err = imlayer.OrderShipTempMsg(custAccount.AccessToken,page,members.OpenID,templateId,prepayId,
							 orderIdStr,order.ShippingCorp,order.ShippingCode,order.DeliverAddress)
	if err != nil {
		beego.Debug("OrderShipTempMsg:", err.Error())
	}
	timestamp := time.Now().Format("200601021504")
        err = imlayer.OrderNotifyMsg(msg.OrderId,order.Status,timestamp)
        if err != nil {
           beego.Debug("OrderNotifyMsg:", err.Error())
        }
	return
}

func TradeWaitRated(message string, out *string){
	var msg event.TradeMsg
	if result, err := event.DecodeMsg(message, &msg); err != nil {
	    beego.Debug("result:", result)
		*out = err.Error()
		return
	}
	orderIdStr := strconv.FormatInt(msg.OrderId, 10)
	//beego.Debug("TradeWaitRated:", msg.MsgHeader.EventType, msg.OrderId)
	order, err := shopping.GetOrderById(msg.OrderId)
	if err != nil {
	    beego.Debug("GetOrderById:", err.Error())
	    return
	}
	members, err := member.GetMemberById(order.MemberId)
	if err != nil {
	    beego.Debug("GetMemberById:", err.Error())
		return
	}
	custAccount, err := isv.GetCustAccountByAppId(members.AppId)
	if err != nil {
		beego.Debug("GetCustAccountByAppId:", err.Error())
		return
	}
	templateId, err := imlayer.GetTemplateId(msg.CompanyId,members.AppId,"AT0503")
	if err != nil {
		beego.Debug("GetTemplateId:", err.Error())
		return
	}
	prepayId, err := im.GetFormIdByOpenId(members.OpenID,"order",orderIdStr)
	if err != nil {
		beego.Debug("GetFormIdByOpenId:", err.Error())
		return
	}
	page := "pages/order/detail/index?order_id=" + orderIdStr
	var itemTitleArr []string
	for _, value := range order.Items {
	    itemTitleArr = append(itemTitleArr, value.Title)
	}
	err = imlayer.OrderRatedTempMsg(custAccount.AccessToken,page,members.OpenID,templateId,prepayId,
	                          orderIdStr,strings.Join(itemTitleArr, ","),"需要您对该笔交易进行评价")
	if err != nil {
		beego.Debug("OrderRatedTempMsg:", err.Error())
	}
        timestamp := time.Now().Format("200601021504")
        err = imlayer.OrderNotifyMsg(msg.OrderId,order.Status,timestamp)
        if err != nil {
            beego.Debug("OrderNotifyMsg:", err.Error())
        }
	return
}

func TradeEnterReturn(message string, out *string){
	//第三方推送队列
	var msg event.TradeMsg
	if result, err := event.DecodeMsg(message, &msg); err != nil {
	    beego.Debug("result:", result)
		*out = err.Error()
		return
	}
	//beego.Debug("TradeEnterReturn:", msg.MsgHeader.EventType, msg.OrderId)
	orders, err := shopping.GetOrderById(msg.OrderId)
	if err != nil {
	    beego.Debug("GetOrderById:", err.Error())
	    return
	}
	if apiInfo, err := misc.GetApiInfo(orders.PartnerId); err == nil {
		paylayer.SendErpMsg(orders.PartnerId,orders.StoreId,orders.OrderId,apiInfo.NotifyUrl,"OrderReturns")
	}else{
	    beego.Debug("GetApiInfo:", err.Error())
	}
	return
}

// 订单管理
type OrdersController struct {
	base.BaseController
}

func (this *OrdersController) TradesList() {
	curRoleId := this.Ctx.Input.GetData("curRoleId").(int) 
	companyId := int64(this.Ctx.Input.GetData("curCompanyId").(int))
	curUserId := int64(this.Ctx.Input.GetData("curUserId").(int))
	if curUserId == 0 {
		this.ServeError("user is not login")
	    return
	}
	query,_,fields,order_by,offset,limit,err := this.GetQueryPara()
	if err != nil {
	   this.ServeError(err.Error())
	   return
	}
	if curRoleId == 1 {
	    query["member_id"] = strconv.FormatInt(curUserId, 10)
	}else if curRoleId == 2 {
	    query["partner_id"] = strconv.FormatInt(companyId, 10)
		if this.CurrentUser != nil {
	        if this.CurrentUser.PartByUser {
		       query["user_id"] = strconv.FormatInt(curUserId, 10)
		    }
	    }
	}else{
	
	}
	var allowStoreId []int64
	if this.CurrentUser != nil {
	    allowStoreId = this.CurrentUser.AllowStoreId
	}
	//beego.Debug("allowStoreId:", allowStoreId)
	l, cnt, err := shopping.GetAllOrders(allowStoreId,query,fields,order_by,offset,limit)
	if err != nil {
	    this.ServeError(err.Error())
		return	
	}
	r := struct {
	    TotalCount int64                  `json:"total_count"`
	    Orders     []*shopping.ValueOrder `json:"orders"`
	}{TotalCount: cnt, Orders: l}
	this.Data["json"] = r
	this.ServeJSON()
}

func (this *OrdersController) OpenTradesGet() {
	//curRoleId := this.Ctx.Input.GetData("curRoleId").(int) 
	companyId := int64(this.Ctx.Input.GetData("curCompanyId").(int))
	curUserId := int64(this.Ctx.Input.GetData("curUserId").(int))
	if curUserId == 0 {
		this.ServeError("user is not login")
	    return
	}
	offset := 0             //default is 0
	limit := 10             //default is 50
	v := struct {
	    StoreId       int64      `form:"store_id"`
		OrderId       string     `form:"order_id"`
		StartCreated  string     `form:"start_created"` 
		EndCreated    string     `form:"end_created"`
		PageSize      int        `form:"page_size"`
		PageNo        int        `form:"page_no"`
		Status        string     `form:"status"`
	}{PageSize:10, PageNo:1}     
	this.ParseForm(&v)
	valid := validation.Validation{}
	valid.Range(v.PageSize,1,1000,"page_size")
	valid.Range(v.PageNo,1,1000,"page_no")
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	v.PageNo = v.PageNo - 1     //为了计算offset
	offset = v.PageNo*v.PageSize
	limit = v.PageSize
	l, cnt, err := shopping.GetOpenApiOrders(companyId,v.StoreId,v.OrderId,v.StartCreated,v.EndCreated,v.Status,offset,limit)
	if err != nil {
	    this.ServeError(err.Error())
		return	
	}
	r := struct {
	    TotalCount int64                  `json:"total_count"`
	    Orders     []*shopping.ValueOrder `json:"orders"`
	}{TotalCount: cnt, Orders: l}
	this.Data["json"] = r
	this.ServeJSON()
}

func (this *OrdersController) Post() {
	var v shopping.ValueOrder
	valid := validation.Validation{}
	this.ParseForm(&v)
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return	
	}
	if err := json.Unmarshal([]byte(v.ItemsJson), &v); err != nil {
		this.ServeError(err.Error())
		return
	}
	if _, err := shopping.AddOrder(&v); err != nil {
        this.ServeError(err.Error())
		return
    }
	for _, item := range v.Items {
	    item.Order = &v                   // pay more attention
	}
	if err := shopping.AddMultiOrderItems(v.Items); err != nil {
		this.ServeError(err.Error())
        return
	}
	rsp := struct {
		OrderId   int64        `json:"order_id"`
	    Created   time.Time  `json:"created"`
	}{OrderId: v.OrderId, Created:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

func (this *OrdersController) Put() {
	var v shopping.ValueOrder
	this.ParseForm(&v)
	valid := validation.Validation{}
	valid.Required(v.OrderIdStr, "order_id")
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	var err error
	if v.OrderId, err = strconv.ParseInt(v.OrderIdStr, 10, 64); err != nil {
	    this.ServeError(err.Error())
		return
	}
	excludeArr := []string{"items","member_id","partner_id","store_id"}
	updateFields, err := this.GetUpdateFields(v, "", "form", excludeArr)
	updateFields = helper.Remove(updateFields,"status")   //不允许更新状态字段
	if err != nil {
	   this.ServeError(err.Error())
		return
	}
    if err := shopping.UpdateOrderById(&v, updateFields...); err != nil{
		this.ServeError(err.Error())
		return
	}
	rsp := struct {
		    OrderId   string      `json:"order_id"`
	        Modified  time.Time   `json:"modified"`
	    }{OrderId:v.OrderIdStr, Modified:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

type ReqPara struct {
	BuyPara []struct {
		SkuId              string `json:"sku_id"`
		Num                int    `json:"num"`
		ActivityId         int64  `json:"activity_id"`
		BargainActId       int64  `json:"bargain_act_id"`
		PintuanId          int64  `json:"pintuan_id"`          //拼团活动id
		PintuanActivityId  int64  `json:"pintuan_activity_id"` //拼团实例id
		ConfessionDetailId int64  `json:"confession_detail_id"` //
		StartDate          string `json:"start_date"`         //开始日期
		EndDate            string `json:"end_date"`           //结束日期
	} `json:"buy_para"`
}

// 买家下单预览
func (this *OrdersController) Preview() {
	var userId int64 = 0
	curUserId := int64(this.Ctx.Input.GetData("curUserId").(int))
	if curUserId == 0 {
		this.ServeCodeError("4011", response.LangConf.Get("4011").MustString())
	    return
	}
	curAppId := this.Ctx.Input.GetData("curAppId").(string)   //buyer role
	//
	if needPrevent, _:= orderlayer.PreventSubmitOrder(curAppId, curUserId); needPrevent {
	    this.ServeCodeError("4011", "此顾客无权下单")
	    return
	}
	v := struct {
	    BuyPara       string   `form:"buy_para"`
		AddressId     int64    `form:"address_id"`  //0，则表示只是预览购物车中商品价格，不形成真正的订单预览，即：预览0;到店消费-1; 外卖订单>0
	    OrderType     int      `form:"order_type"`      //类型:0一般订单4拼团订单
		FxRef         string   `form:"fx_ref"`          //分销来源
		PickpointId   int64    `form:"pickpoint_id"`    //自提点id
		ExpressId     int64    `form:"express_id"`      //表白id
		StepExpressId int64    `form:"step_express_id"` //阶梯运费模板编号
		UserId        string   `form:"user_id"`
		Note          string   `form:"note"`
		FoodId        string   `form:"food_id"`         //餐饮特有参数
		ReceiverTime  string   `form:"receiver_time"`   //要求到货时间
	}{}  
	this.ParseForm(&v)
	valid := validation.Validation{}
	valid.Required(v.BuyPara,   "buy_para")
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
	    return
	}
	flowType := 0
	if v.AddressId < 0 {
	    flowType = 1
	}
	if len(v.UserId) > 0 {
	    userId, _= strconv.ParseInt(v.UserId, 10, 64)
	}
	orders, err := this.corePreviewLogic(userId,curUserId,v.AddressId,v.PickpointId,v.ExpressId,v.StepExpressId,curAppId,v.BuyPara,v.FxRef,v.Note,v.FoodId,v.ReceiverTime,v.OrderType,flowType)
	if err != nil {
	    this.ServeError(err.Error())
	    return      
	}
	this.Data["json"] = orders
	this.ServeJSON()
}

// 卖家帮买家匿名下单预览
func (this *OrdersController)AnonymousPreview() {
	v := struct {
	    BuyPara       string   `form:"buy_para"`
		AppId         string   `form:"app_id"`
	}{}  
	this.ParseForm(&v)
	valid := validation.Validation{}
	valid.Required(v.BuyPara, "buy_para")
	valid.Required(v.AppId,   "app_id")
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
	    return
	}
	var memberId int64 = 0
	orders, err := this.corePreviewLogic(0,memberId, -1, 0, 0, 0, v.AppId, v.BuyPara, "", "", "", "", 0, 2)
	if err != nil {
	    this.ServeError(err.Error())
	    return      
	}
	this.Data["json"] = orders
	this.ServeJSON() 
}

//关联买家和订单
func (this *OrdersController) RelatedOrder() {
	v := struct {
	    OrderId    string  `form:"order_id" valid:"Required"`
		MemberId   int64   `form:"member_id" valid:"Required"`
	}{} 
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	//curPartnerId := this.Ctx.Input.GetData("curCompanyId").(int)
	orderId, _ := strconv.ParseInt(v.OrderId, 10, 0)
	orders, err := shopping.GetOrderById(orderId)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	if orders.Status != "S_ORDER_WAIT_PAYMENT" {
	    this.ServeError("order status is not correct")
		return     
	}
	_, err = member.GetMemberById(v.MemberId)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	orders.MemberId = v.MemberId
	err = shopping.UpdateOrderMemberId(orders)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	orders.FlowType = 1
	err = shopping.UpdateOrderFlowType(orders)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	this.Data["json"] = orders
	this.ServeJSON()
}

func (this *OrdersController)corePreviewLogic(userId,memberId,addressId,pickpointId,expressId,  
        stepExpressId int64,curAppId,buyPara,fxRef,note,foodId,receiverTime string,orderType,flowtype int) (*shopping.ValueOrder, error){
    var (
	    addr             *member.DeliverAddr = new(member.DeliverAddr)
	    partnerId        int64
	    storeId          int64
	    //itemFareNum      map[string]map[int64]int = make(map[string]map[int64]int)  //map[item_id]map[fare_id]num
		itemFreePostage  map[string]int =  make(map[string]int)                     // map[item_id]num, 免邮商品列表
		sumPackingFee    float32 = 0.00
		sumTotalFee      float32 = 0.00
		sumDiscountFee   float32 = 0.00
		sumWeight        float32 = 0.00
		sumItemTax       float32 = 0.00
		defaultCarryWay  string
		fareModels       []*seller.FareModel
	)
    orders := new(shopping.ValueOrder)
	u := ReqPara{}
	err := json.Unmarshal([]byte(buyPara), &u)
    if err != nil {
		return nil, errors.New("订单入参JSON解析错误")    
    }
	acPay, err := isv.GetParamsByAppIdOrSubAppId(curAppId)
	if err != nil {
	   err = errors.Wrap(err, "GetParamsByAppIdOrSubAppId... ")
	   return nil, err
	}
	if acPay.PayWayId == 16 {
	    orders.OrderId, err = helper.CreateSpecOrderId(acPay.PemKey)
		if err != nil {
		   err = errors.Wrap(err, "CreateSpecOrderId... ")
	       beego.Debug(err.Error())
		   return nil, err
		}
	} else {
	    orders.OrderId, _ = uuid.GetSnowFlakeId(uuid.Worker)
	}
	orders.AppId = curAppId
	orders.FxRef = fxRef
	orders.PickpointId = pickpointId
	orders.Note = note
	orders.FoodId = foodId
	orders.ReceiverTimeStr = receiverTime
	if len(orders.ReceiverTimeStr) > 0 {
		orders.ReceiverTime, _ = time.Parse(consts.DATETIME_FORMAT, orders.ReceiverTimeStr)
	}
	orders.OrderFrom  = 0
	orders.OrderType = orderType
	orders.PayWayCode = 1
	for _, value := range u.BuyPara {
		sku_id, _:= strconv.ParseInt(value.SkuId, 10, 64)
		quantity := int32(value.Num)
		sku, err := sale.GetSkuBySkuId(sku_id)
		if err != nil {
		    return nil, errors.New("无效规格不能添加到订单")
		}
		if sku.StatusId == 2 {
			return nil, errors.New("规格已经删除")
		}
		item, err := sale.GetItemByItemId(sku.Item.ItemId)
		if err != nil {
			return nil, errors.New("无效商品不能添加到订单")
	    }
		if item.StatusId == 2 {
		    return nil, errors.New("商品已经删除")
		}
		if item.OnShelves == 0 {
		    return nil, errors.New("商品已经下架")
		}
		if item.IsInclPostage == 2 && item.FareId == 0 {                                  //无效运费模板商品不能添加到订单
			beego.Debug("temp fare is invalid,item_id: %d", sku.Item.ItemId)
			return nil, errors.New("无效运费模板商品不能添加到订单")
		}
		partnerId = item.PartnerId
		storeId = item.StoreId
		pOrderItem := new(shopping.OrderItem)
		pOrderItem.Order = orders
		pOrderItem.ItemId = item.ItemId
		pOrderItem.SkuId = sku.SkuId
		pOrderItem.ItemIdStr = strconv.FormatInt(item.ItemId, 10)
		pOrderItem.SkuIdStr = strconv.FormatInt(sku.SkuId, 10)  
		pOrderItem.Title = item.Title
		pOrderItem.SkuProperties = sku.SkuProperties
		pOrderItem.Image = /*item.Image*/sku.ImgUrl
		pOrderItem.Quantity = quantity
		pOrderItem.SkuStocks = sku.SkuStocks      //无需存储
		pOrderItem.LimitPay = item.LimitPay      //
		pOrderItem.StartDate = value.StartDate
		pOrderItem.EndDate = value.EndDate
		pOrderItem.DeliveryAddrs = item.DeliveryAddrs
		pOrderItem.OuterId = item.OuterId
		pOrderItem.SkuOuterId = sku.SkuOuterId
		pOrderItem.Barcode = sku.Barcode
		pOrderItem.Xtype = item.Xtype
		pOrderItem.IsVirtual = item.IsVirtual
		if value.ActivityId > 0 {
		    pOrderItem.ActivityId = value.ActivityId
		}else{
		    pOrderItem.ActivityId = 0
		}
		if value.BargainActId > 0 {
			bargainActivity, err := shopping.GetBargainActivityById(value.BargainActId)
			if err == nil {
			    //校验此BargainActId是否已经使用过,只能使用一次
				if bargainActivity.IsUsed == 0 {
				    pOrderItem.BargainActId = value.BargainActId
				}
			    //校验是否满足最低砍价次数
                if bargainRule, err := shopping.GetBargainRuleById(bargainActivity.BargainRuleId); err == nil {
				    if bargainActivity.TotalBargainTimes < bargainRule.MinBargainTimes {
						beego.Debug("total_cut_off_fee is less than min_bargain_times:%d,%d",bargainActivity.TotalBargainTimes,bargainRule.MinBargainTimes)
						return nil, errors.New("砍价次数小于规则所需") 
					}
				}else{
					beego.Debug("bargain activity rule is invalid,bargain_rule_id: %d", bargainActivity.BargainRuleId)
					return nil, errors.New("砍价规则无效") 
				}
            }else{
				beego.Debug("bargain activity is invalid,bargain_act_id: %d", value.BargainActId)
				return nil, errors.New("砍价活动无效") 
			}
		}else{
		    pOrderItem.BargainActId = 0
		}
		if value.PintuanActivityId > 0 {
			if activity, err := shopping.GetPintuanActivityById(value.PintuanActivityId); err != nil {
			    return nil, errors.New("拼团活动无效")
			}else{
			    if activity.CurrentCustomerNum >= activity.NeedCustomerNum {
					beego.Debug("pintuan activity current_customer_num gte need_customer_num,pintuan_activity_id:", value.PintuanActivityId)
			        return nil, errors.New("拼团所需客户数已经满足")
                }
			    pOrderItem.Price = activity.PinPrice
			}
			pOrderItem.PintuanId = value.PintuanId
			pOrderItem.PintuanActivityId = value.PintuanActivityId
			orders.OrderType = 4
			if err = PinTuanCheck(value.PintuanId,storeId,memberId,value.PintuanActivityId); err != nil {
			    return nil, errors.New("拼团规则校验无效")
			}
		} else {
		    if value.PintuanId > 0 {
				if pintuan, err := shopping.GetPintuanById(value.PintuanId); err != nil {
					beego.Debug("GetPintuanById id error:", value.PintuanId, err.Error())
			        return nil, errors.New("拼团规则无效")
				}else{
				    pOrderItem.Price = pintuan.PinPrice
				}
				pOrderItem.PintuanId = value.PintuanId
				orders.OrderType = 4
				if err = PinTuanCheck(value.PintuanId,storeId,memberId,0); err != nil {
			        return nil, errors.New("拼团规则校验无效")   
				}
			} else {
			    pOrderItem.Price = sku.SkuPrice
			}
		}
		pOrderItem.PackingFee = math.MultiTotalPrice(item.PackingFee, quantity)
		pOrderItem.TotalFee = math.MultiTotalPrice(pOrderItem.Price, quantity)
		pOrderItem.Weight = math.MultiTotalPrice(item.Weight, quantity)
		if pOrderItem.ActivityId > 0 {
		    if oneDiscountFee, err := shopping.GetDiscountFee(sku.Item.ItemId,sku_id,pOrderItem.ActivityId,pOrderItem.Price,memberId); err == nil {
			    pOrderItem.DiscountFee = math.MultiTotalPrice(oneDiscountFee, quantity)
			    pOrderItem.DiscountSrc=strconv.FormatInt(pOrderItem.ActivityId, 10)+","+strconv.FormatFloat(float64(pOrderItem.DiscountFee), 'f', -1, 32)+";"	
			}else{
			    beego.Debug("GetDiscountFee error:", err.Error())
			}
		}else{
		    pOrderItem.DiscountFee = 0
		}
		if pOrderItem.BargainActId > 0 {    //有砍价优惠，则用砍价优惠
		    if oneBargainActFee, err := shopping.GetBargainDiscountFee(pOrderItem.BargainActId); err == nil {
			    totalBargainActFee := math.MultiTotalPrice(oneBargainActFee, quantity)
				if totalBargainActFee > 0 {
				    pOrderItem.DiscountFee = totalBargainActFee
					pOrderItem.DiscountSrc=pOrderItem.DiscountSrc+strconv.FormatInt(pOrderItem.BargainActId, 10) +","+strconv.FormatFloat(float64(pOrderItem.DiscountFee), 'f', -1, 32)
				}
			}else{
			    beego.Debug("GetBargainDiscountFee error:", err.Error())
			}
		}
		pOrderItem.Payment = math.SubPrice(pOrderItem.TotalFee, pOrderItem.DiscountFee)
		pOrderItem.ItemTax = math.MultiFloat32Price(sku.TaxRate, pOrderItem.Payment + pOrderItem.PackingFee)
		//
		orders.Items = append(orders.Items, pOrderItem)
		/***********price sums up*****************/
		sumTotalFee = sumTotalFee + pOrderItem.TotalFee
		sumPackingFee = sumPackingFee + pOrderItem.PackingFee
		sumDiscountFee = sumDiscountFee + pOrderItem.DiscountFee
		/***********price sums up*****************/
		sumWeight = sumWeight + pOrderItem.Weight
		sumItemTax = sumItemTax + pOrderItem.ItemTax
		
		if item.IsInclPostage == 1 {
			if tmp, ok := itemFreePostage[pOrderItem.ItemIdStr]; ok {
				itemFreePostage[pOrderItem.ItemIdStr] = tmp + value.Num
			}else{
				itemFreePostage[pOrderItem.ItemIdStr] = value.Num
			}						
		}else{
			fare, err := seller.GetFareTemplateById(item.FareId)
			if err != nil {
				beego.Debug("temp fare is invalid,item_id:", sku.Item.ItemId)
				return nil, errors.New("无效运费模板商品不能添加到订单") 
			}
			if fare.IsInclPostage == 1 {
				if tmp, ok := itemFreePostage[pOrderItem.ItemIdStr]; ok {
					itemFreePostage[pOrderItem.ItemIdStr] = tmp + value.Num
				}else{
					itemFreePostage[pOrderItem.ItemIdStr] = value.Num
				}
			}else{
				fareModels,_= seller.PushItem(fareModels,pOrderItem.ItemIdStr,item.FareId,fare.ValuationModel,value.Num,item.Weight,0.0)
			}
		}
		pOrderItem.OrderId = strconv.FormatInt(orders.OrderId, 10)
		if value.ConfessionDetailId > 0 {
		    actS := struct {
				ConfessionDetailId  int64   `json:"confession_detail_id"`
			}{ConfessionDetailId: value.ConfessionDetailId}
		    if b, err := json.Marshal(actS); err == nil {
			   pOrderItem.ActJson = string(b)
			}
		}
    }
	orders.MemberId = memberId
	orders.PartnerId = partnerId
	orders.StoreId = storeId
	orders.UserId = userId
	if addressId > 0 {
	    addr, err = member.GetDeliverAddrById(addressId)
		if err != nil {
			return nil, errors.New("配送地址无效")      
		}
		orders.DeliverName = addr.RealName
		orders.Email = addr.Email
		orders.DeliverPhone = addr.Mobile
		orders.Country = addr.Country
		orders.Province = addr.Province
		orders.City = addr.City
		orders.District = addr.District
		orders.DeliverAddress = addr.Address
		orders.PostCode = addr.PostCode
	}
	orders.Status = "S_ORDER_WAIT_PAYMENT"
	orders.Weight = sumWeight
	/******About Price ******/
	if addressId > 0 {
		if defaultCarryWay,orders.PostFee,fareModels,err = seller.GetPostAges(fareModels,int64(addr.CityId)); err != nil {
		    return nil, errors.New("运费计算错误")    
		}
		orders.PostDetails = seller.OutputCarryFee(defaultCarryWay, fareModels)
		//进一步阶梯运费计算
		if stepExpressId > 0 {
			if distance, err := orderlayer.CalcDeliveryDistance(addressId, storeId); err == nil {
			    beego.Debug("stepExpressId distance:", distance,"Weight:",orders.Weight,"DeliverTime:", orders.DeliverTime)
				tmpPostFee,err := seller.GetStepFreightFee(partnerId,storeId,stepExpressId,float32(distance/1000),orders.Weight,orders.DeliverTime)
			    if err == nil {
				   orders.PostFee = math.MultiTotalPrice(tmpPostFee, 1)
				   orders.PostDetails = nil
			    }else{
			       beego.Debug(err.Error())
				   return nil, err 
			    }
			}else{
			    beego.Debug(err.Error())
			}
		}
	}else{
	    orders.PostFee = 0
	}
	//订单级满减优惠计算
	orders.TotalFee = math.SubPrice(sumTotalFee, 0.00)
	orders.DiscountFee = sumDiscountFee  //商品级优惠
	orders.PackingFee = sumPackingFee
	orders.MjsDiscountFee = 0
	orders.TotalTax = sumItemTax
	if curActId,actDiscountMap,err := shopping.GetMjsDiscountFee(partnerId,storeId,addr.CityId,orders.PostFee,orders); err == nil {
	    if v, ok := actDiscountMap[curActId]; ok {
		    orders.MjsActivityId = curActId
			orders.MjsDiscountFee = v.Discount
			orders.DiscountDetails = actDiscountMap
			if v.CutPostFee == 1 {
			   orders.PostFee = 0
			}
		}
	}
	if curActId,actMbyMap,err := shopping.GetMbyPostFee(partnerId,storeId,addr.CityId,orders.PostFee,orders); err == nil {
	    if v, ok := actMbyMap[curActId]; ok {
		    orders.MbyActivityId = curActId
			orders.MbyDetails = actMbyMap
			if v.CutPostFee == 1 {
			   orders.PostFee = 0
			}
		}
	}
	actIdJson := struct {
		ExpressId     int64  `json:"express_id,omitempty"`
	    MjsActivityId int64  `json:"mjs_activity_id,omitempty"`
		MbyActivityId int64  `json:"mby_activity_id,omitempty"`
	}{ExpressId:expressId,MjsActivityId:orders.MjsActivityId,MbyActivityId:orders.MbyActivityId}
	if actJsonData, err := json.Marshal(&actIdJson); err == nil {
	    orders.ActJson = string(actJsonData)
	}
	orders.Payment = math.SubPrice(orders.TotalFee+orders.PostFee+orders.TotalTax,orders.DiscountFee+orders.MjsDiscountFee)
	if orders.Payment <= 0 {
	    orders.MjsActivityId = 0
		orders.MjsDiscountFee = 0.0
		orders.DiscountDetails = nil
		orders.Payment = math.SubPrice(orders.TotalFee+orders.PostFee+orders.TotalTax,orders.DiscountFee+orders.MjsDiscountFee)
	}
	orders.Payment = math.SubPrice(orders.Payment + orders.PackingFee, 0)
	orders.BalanceDiscount = 0
	orders.AdjustFee = 0
	orders.RefundAmount = 0
	/******About Price ******/
	orders.OrderIdStr = strconv.FormatInt(orders.OrderId, 10)
	orders.FlowType = flowtype
	if accountAll,err := orderlayer.GetAssignMoney(orders.Items,partnerId,storeId,orders.OrderId); err == nil {
	   if len(accountAll.AccountItems) > 0 {
	       if b, e := json.Marshal(accountAll); e == nil {
			  orders.AccountJson = string(b)
		   }
	   } 
	}
	//beego.Debug("orders.AccountJson:", orders.AccountJson)
	//
	redisconn := redisgo.GetInstance()
	if orderJSON, err := json.Marshal(orders); err == nil {
		if _, err = redisconn.Set(orders.OrderIdStr, string(orderJSON), 5*60); err != nil {
			beego.Debug("SETEX", err.Error())
		}
	}
	//对于非自提的订单,缓存运送方式信息
	if addressId > 0 {
		//orders.Payment = math.SubPrice(orders.Payment + orders.PackingFee, 0)
		postData := seller.CarryFeeCacheData{OrderIdStr:orders.OrderIdStr,DefaultPostWay:defaultCarryWay,ItemFareModels:fareModels}
		if postDataJSON, err := json.Marshal(&postData); err == nil {
			key := "postdata_" + orders.OrderIdStr
			if _, err = redisconn.Set(key, string(postDataJSON), 5*60); err != nil {
				beego.Debug("SETEX", err.Error())
			}
		}
	}
	return orders, nil
}

func PinTuanCheck(pintuanId,storeId,memberId,pintuanActivityId int64) error {
    type PinTuanCheckReq struct {
		Method   string `json:"method"`                                    //
		Content struct {
			PintuanId         string `json:"pintuan_id"`                    //拼团活动id 
			StoreId           string `json:"store_id"`                      //店铺id 
			MemberId          string `json:"member_id"`                     //用户id 
			PintuanActivityId string `json:"pintuan_activity_id,omitempty"` //拼团实例id 
		} `json:"content"`
	}
	req := PinTuanCheckReq{}
	req.Method = "dhf.pintuan.activity.testing"
	req.Content.PintuanId = strconv.FormatInt(pintuanId, 10)
	req.Content.StoreId = strconv.FormatInt(storeId, 10)
	req.Content.MemberId = strconv.FormatInt(memberId, 10)
	req.Content.PintuanActivityId = strconv.FormatInt(pintuanActivityId, 10)
	reqJson, err := json.Marshal(&req)
	if err != nil {
	    beego.Debug("Marshal error:", err.Error())
		return err
	}
	reqUrl := beego.AppConfig.String("PHPApiUrl") + "/api/rest"
	client := core.GetPostProxyClient()
	_, rsp, err := client.Excute("POST", reqUrl, reqJson)
	if err != nil {
		beego.Debug("rsp error:", err.Error())
		return err
	}
	rslt := struct {
		Result   int    `json:"result"` 
		ErrorMsg string `json:"errormsg"` 
	}{}
	if err := json.Unmarshal(rsp, &rslt); err != nil {
        return err
	}
	if rslt.Result == 1 {
	    return errors.New(rslt.ErrorMsg) 
	}
	return nil
}

func (this *OrdersController) DiscountUpdate() {
	var (
		skuAndDiscountMap map[string]float32 = make(map[string]float32)
		sumDiscountFee   float32 = 0.00
	)
	v := struct {
	    OrderId         string   `form:"order_id" valid:"Required"`
		AdjustFee       float32  `form:"adjust_fee"`
		AdjustDiscounts string   `form:"adjust_discounts"`
	}{} 
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	curPartnerId := this.Ctx.Input.GetData("curCompanyId").(int)
	orderId, _ := strconv.ParseInt(v.OrderId, 10, 0)
	if ok := shopping.CheckOrderExistByPartner(int64(curPartnerId), orderId); !ok {
	    this.ServeError("order is not exist")
	    return
	}
	orders, err := shopping.GetOrderById(orderId)
	if err != nil {
        this.ServeError(err.Error())
		return      
    }
	if orders.Status != "S_ORDER_WAIT_PAYMENT" {
	    this.ServeError("order status is not correct")
		return     
	}
    if len(v.AdjustDiscounts) > 3 {
	    req := struct {
			AdjustPara []struct {
				SkuId     string   `json:"sku_id"`
				Discount  float32  `json:"discount"`
			} `json:"adjust_discounts"`
		}{}
	    err := json.Unmarshal([]byte(v.AdjustDiscounts), &req)
		if err != nil {
			this.ServeError(err.Error())
			return
		}
	    for _, value := range req.AdjustPara {
           skuAndDiscountMap[value.SkuId] = value.Discount
        }
	}
    for _, orderItem := range orders.Items {
	    orderItem.SkuIdStr = strconv.FormatInt(orderItem.SkuId, 10)
		if tmp, ok := skuAndDiscountMap[orderItem.SkuIdStr]; ok {
		    if tmp > orderItem.TotalFee {
                this.ServeError("优惠大于了商品的应付金额")
				return
            }
			orderItem.DiscountFee = 0.0 + tmp
			orderItem.Payment = math.SubPrice(orderItem.TotalFee, orderItem.DiscountFee)
			sumDiscountFee = sumDiscountFee + orderItem.DiscountFee
		}else{
		    this.ServeError("sku_id discount_fee is full")
			return
		}
	}
	orders.DiscountFee = sumDiscountFee
	orders.AdjustFee = v.AdjustFee
	tempPayment := orders.TotalFee + orders.PostFee + orders.AdjustFee
	orders.Payment = math.SubPrice(tempPayment, orders.DiscountFee)
	if err = shopping.UpdateOrderDiscountById(orders); err == nil {
	    for _, orderItem := range orders.Items {
		    orderItem.SkuIdStr = strconv.FormatInt(orderItem.SkuId, 10)
			if _, ok := skuAndDiscountMap[orderItem.SkuIdStr]; ok {
				if err = shopping.UpdateOrderItemDiscountById(orderItem); err != nil {
				    beego.Debug("UpdateOrderItemDiscountById:" + err.Error())
				}
		    }
		}
	}
	//由于微信支付的问题，所以需要对订单号也进行更改
	orders.Status = "S_ORDER_CANCEL"
	if err = shopping.UpdateOrderStatus(orders); err != nil {
	    beego.Debug("UpdateOrderStatus:", err.Error())
	    this.ServeError(err.Error())
		return
	}
	oldOrderId := orders.OrderId
	newOrderId, err := helper.ModifyOrderId(oldOrderId)
	if err != nil {
	    beego.Debug("ModifyOrderId:", err.Error())
	    this.ServeError(err.Error())
		return
	}
	orders.Status = "S_ORDER_WAIT_PAYMENT"
	orders.OrderId = newOrderId
	if _, err := shopping.AddOrder(orders); err != nil {
		err = errors.Wrap(err, "AddOrder... ")
		this.ServeError(err.Error())
        return
	}
	for _, orderItem := range orders.Items {
	    orderItem.OrderItemId = 0
		orderItem.Order = orders
		if _, err := shopping.AddOrderItem(orderItem); err != nil {
			err = errors.Wrap(err, "AddOrderItem... ")
			this.ServeError(err.Error())
			return
	    }
	}
	modifyMsg := struct {
		OldOrderId int64  `json:"old_order_id"`  
		NewOrderId int64  `json:"new_order_id"`
        PartnerId  int64  `json:"partner_id"`
		StoreId    int64  `json:"store_id"`
		Kind       string `json:"kind"`
	}{OldOrderId:oldOrderId,NewOrderId:newOrderId,PartnerId:orders.PartnerId,StoreId:orders.StoreId}
	modifyJson, err := json.Marshal(&modifyMsg)
	if err != nil {
		beego.Debug(err.Error())
		return
	}
	address := beego.AppConfig.String("NsqUrl")
	topic := "OrderIdChange"
	if err = nsqcli.StartProducer(address, topic, modifyJson); err != nil {
		beego.Debug("StartProducer err:", err.Error())
	}
	shopping.DeleteOrder(oldOrderId)
	rsp := struct {
		OrderId   string      `json:"order_id"`
	    Modified  time.Time   `json:"modified"`
	}{OrderId:strconv.FormatInt(orders.OrderId, 10), Modified:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

type PostPutPara struct {
	DetailWay []struct {
		ItemId  string `json:"item_id"`
		Sway    string `json:"sway"`
	} `json:"datail_way"`
}

// 更新优惠方式
func (this *OrdersController) MjsDiscountPut() {
	curUserId := int64(this.Ctx.Input.GetData("curUserId").(int))
	if curUserId == 0 {
		this.ServeError("user is not login")
	    return
	}
	v := struct {
	    OrderId        string `form:"order_id"`
		MjsActivityId  int64  `form:"mjs_activity_id"`
		TypeId         int    `form:"type_id"`
	}{}  
	this.ParseForm(&v)
	valid := validation.Validation{}
	valid.Required(v.OrderId, "order_id")
	valid.Required(v.MjsActivityId, "mjs_activity_id")
	valid.Required(v.TypeId, "type_id")
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
	    return
	}
	redisconn := redisgo.GetInstance()
	if ok, _:= redisconn.Exists(v.OrderId); !ok {
		this.ServeError("Order is not exist,Please re-order")
		return
	}
	orders := new(shopping.ValueOrder)
	if cacheValue, err := redisconn.GetString(v.OrderId); err == nil && len(cacheValue) > 20  {
		if err = json.Unmarshal([]byte(cacheValue), orders); err != nil {
			this.ServeError(err.Error())
		    return     
		}
	} else {
	    this.ServeError(err.Error())
		return
	}
	var err error
	if orders.OrderId, err = strconv.ParseInt(orders.OrderIdStr, 10, 64); err != nil {
	    this.ServeError(err.Error())
		return
	}
	if orders.Status != "S_ORDER_WAIT_PAYMENT" {
	    this.ServeError("order status is not correct")
		return     
	}
	if v.TypeId == 1 {
	    if _, ok := orders.DiscountDetails[v.MjsActivityId]; !ok {
			this.ServeError("mjs_activity_id is not invalid")
			return 
		}
		orders.MjsActivityId = v.MjsActivityId
		orders.MjsDiscountFee = orders.DiscountDetails[v.MjsActivityId].Discount
		if orders.DiscountDetails[v.MjsActivityId].CutPostFee == 1 {
			orders.PostFee = 0
		}
		if orders.DiscountDetails[v.MjsActivityId].CutPostFee == 0 {
			orders.PostFee = orders.DiscountDetails[v.MjsActivityId].PostFee
		}
	} else if v.TypeId == 2 {
	    if _, ok := orders.MbyDetails[v.MjsActivityId]; !ok {
			this.ServeError("mjs_activity_id is not invalid")
			return 
		}
		orders.MbyActivityId = v.MjsActivityId
		if orders.MbyDetails[v.MjsActivityId].CutPostFee == 1 {
			orders.PostFee = 0
		}
		if orders.MbyDetails[v.MjsActivityId].CutPostFee == 0 {
			orders.PostFee = orders.MbyDetails[v.MjsActivityId].PostFee
		}
	} else {
	    this.ServeError("type_id is invalid")
		return
	}
	orders.Payment = math.SubPrice(orders.TotalFee + orders.PostFee+orders.TotalTax, orders.DiscountFee + orders.MjsDiscountFee)
    if orderJSON, err := json.Marshal(orders); err == nil {
		if _, err = redisconn.Set(orders.OrderIdStr, string(orderJSON), 5*60); err != nil {
			beego.Debug("SETEX", err.Error())
		}	
	}
	this.Data["json"] = orders
	this.ServeJSON()
}

// 更新快递方式
func (this *OrdersController) CarryWayPut() {
	var (
		result            float32 = 0.0
	)
	curUserId := int64(this.Ctx.Input.GetData("curUserId").(int))
	if curUserId == 0 {
		this.ServeError("user is not login")
	    return
	}
	v := struct {
	    OrderId       string   `form:"order_id"`
		GroupWay      string   `form:"group_way"`
		DatailWay     string   `form:"datail_way"`
	}{}  
	this.ParseForm(&v)
	valid := validation.Validation{}
	valid.Required(v.OrderId, "order_id")
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
	    return
	}
	redisconn := redisgo.GetInstance()
	if ok, _:= redisconn.Exists(v.OrderId); !ok {
		this.ServeError("Order is not exist,Please re-order")
		return
	}
	order := new(shopping.ValueOrder)
	if cacheValue, err := redisconn.GetString(v.OrderId); err == nil && len(cacheValue) > 20  {
		if err = json.Unmarshal([]byte(cacheValue), order); err != nil {
			this.ServeError(err.Error())
		    return     
		}
	} else {
	    this.ServeError(err.Error())
		return
	}
	var err error
	if order.OrderId, err = strconv.ParseInt(order.OrderIdStr, 10, 64); err != nil {
	    this.ServeError(err.Error())
		return
	}
	key := "postdata_" + v.OrderId
	if ok, _:= redisconn.Exists(key); !ok {
		this.ServeError("Post data is not exist,Please re-order")
		return
	}
	postData := seller.CarryFeeCacheData{}
	if cacheValue, err := redisconn.GetString(key); err == nil && len(cacheValue) > 20  {
		if err = json.Unmarshal([]byte(cacheValue), &postData); err != nil {
			this.ServeError(err.Error())
		    return     
		}
	} else {
	    this.ServeError(err.Error())
		return
	}
	fareModels := postData.ItemFareModels
	defaultCarryWay := postData.DefaultPostWay
	if len(v.GroupWay) > 0 {
		if v.GroupWay == "express" {
		   for _, value := range fareModels {
			  result = result + value.ExpressFee
		   }
		}
		if v.GroupWay == "ems" {
		   for _, value := range fareModels {
			   result = result + value.EmsFee
			}
		}
		if v.GroupWay == "post" {
		   for _, value := range fareModels {
			  result = result + value.PostFee 
		   }
		}
	}
	if len(v.DatailWay) > 0  {
		u := PostPutPara{}
		err := json.Unmarshal([]byte(v.DatailWay), &u)
		if err != nil {
			this.ServeError(err.Error())
			return      
		}
		itemCarryModeMap := make(map[string]string)
		for _, value := range u.DetailWay {
		    itemCarryModeMap[value.ItemId] = value.Sway
		}
		if defaultCarryWay == "express" {
		   for _, value := range fareModels {
			   if carryMode, ok := itemCarryModeMap[value.ItemId]; ok {
				   result = result + seller.GetOtherPostFee(carryMode, value)
			   }else{
			       result = result + value.ExpressFee
			   } 
			}
		}
		if defaultCarryWay == "ems" {
		   for _, value := range fareModels {
			   if carryMode, ok := itemCarryModeMap[value.ItemId]; ok {
				   result = result + seller.GetOtherPostFee(carryMode, value)
			   }else{
			      result = result + value.EmsFee
			   }  
			}
		}
		if defaultCarryWay == "post" {
		   for _, value := range fareModels {
			   if carryMode, ok := itemCarryModeMap[value.ItemId]; ok {
				   result = result + seller.GetOtherPostFee(carryMode, value)
			   }else{
			       result = result + value.PostFee
			   }  
			}
		}
	}
	feeExceptPost := order.Payment - order.PostFee
	order.PostFee = math.MultiTotalPrice(result, 1)
	order.Payment = feeExceptPost + order.PostFee
	order.PostDetails = seller.OutputCarryFee(v.GroupWay,fareModels)
	//
    if orderJSON, err := json.Marshal(order); err == nil {
		if _, err = redisconn.Set(order.OrderIdStr, string(orderJSON), 5*60); err != nil {
			beego.Debug("SETEX", err.Error())
		}
	}
	// 缓存运送方式信息等
	savePostData := seller.CarryFeeCacheData{OrderIdStr:order.OrderIdStr,DefaultPostWay:defaultCarryWay,ItemFareModels:fareModels}
	if postDataJSON, err := json.Marshal(&savePostData); err == nil {
		key := "postdata_" + order.OrderIdStr
		if _, err = redisconn.Set(key, string(postDataJSON), 5*60); err != nil {
			beego.Debug("SETEX", err.Error())
		}
	}
	this.Data["json"] = order
	this.ServeJSON()
}

// 买家下单确认 或者 商家代买家下单确认
func (this *OrdersController) Confirm() {
    curUserId := int64(this.Ctx.Input.GetData("curUserId").(int))
	if curUserId == 0 {
		this.ServeError("user is not login")
	    return
	}
	v := struct {
		OrderIdStr string   `form:"order_id"`
	}{}  
	this.ParseForm(&v)
	valid := validation.Validation{}
	valid.Required(v.OrderIdStr, "order_id")
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
	    return
	}
	redisconn := redisgo.GetInstance()
	if ok, _:= redisconn.Exists(v.OrderIdStr); !ok {
		this.ServeError("Order is not exist,Please re-order")
		return
	}
	order := new(shopping.ValueOrder)
	if cacheValue, err := redisconn.GetString(v.OrderIdStr); err == nil && len(cacheValue) > 20  {
		if err = json.Unmarshal([]byte(cacheValue), order); err != nil {
			this.ServeError(err.Error())
		    return     
		}
	} else {
	    this.ServeError(err.Error())
		return
	}
	var err error
	if order.OrderId, err = strconv.ParseInt(order.OrderIdStr, 10, 64); err != nil {
	    this.ServeError(err.Error())
		return
	}
	_, _, err = paylayer.JudgeAndReduceStock(order)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	if len(order.ReceiverTimeStr) > 0 {
	    order.ReceiverTime, _ = time.Parse(consts.DATETIME_FORMAT,order.ReceiverTimeStr)
	}
	if _, err := shopping.AddOrder(order); err != nil {
		err = errors.Wrap(err, "AddOrder... ")
		this.ServeError(err.Error())
        return
	}
	for _, orderItem := range order.Items {
	    orderItem.Order = order
		orderItem.ItemId, _ = strconv.ParseInt(orderItem.ItemIdStr, 10, 64)
		orderItem.SkuId, _ = strconv.ParseInt(orderItem.SkuIdStr, 10, 64)
		if _, err := shopping.AddOrderItem(orderItem); err != nil {
			err = errors.Wrap(err, "AddOrderItem... ")
			this.ServeError(err.Error())
			return
	    }
		//过期使用过的砍价活动
		if orderItem.BargainActId > 0 {
		    m := &shopping.BargainActivity{BargainActivityId:orderItem.BargainActId,IsUsed:1}
			shopping.UpdateBargainActivityById(m, "is_used")
		}
	}
	this.Data["json"] = order
	this.ServeJSON()
}

// 买家取消订单
func (this *OrdersController) StatusCancel() {
	v := struct {
	    OrderId      string   `form:"order_id" valid:"Required"`
		Event        string   `form:"event" valid:"Required"`
	}{Event:"E_ORDER_CANCEL" } 
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	//curUserId := this.Ctx.Input.GetData("curUserId").(int)
	orderId, _ := strconv.ParseInt(v.OrderId, 10, 0)
	order, err := shopping.GetOrderById(orderId)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	var result string = ""
	var req = new(event.TradeMsg)
	req.CompanyId = order.PartnerId
	req.UserId = order.MemberId
	req.OrderId = orderId
	req.MsgHeader.EventType = v.Event
	message, err := event.EncodeMsg(req)
	if err != nil {
        this.ServeError(err.Error())
		return      
    }
	event.KernelBus.Publish(v.Event,message,&result)
	if len(result) > 0 {
		this.ServeError(result)
		return
	}
	rsp := struct {
		    OrderId   string      `json:"order_id"`
	        Modified  time.Time   `json:"modified"`
	    }{OrderId:v.OrderId, Modified:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

//买家收货确认
func (this *OrdersController) BuyerReceive() {
	v := struct {
	    OrderId      string   `form:"order_id" valid:"Required"`
		Event        string   `form:"event" valid:"Required"`
	}{Event:"E_ORDER_RECEIVE" } 
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	//curUserId := this.Ctx.Input.GetData("curUserId").(int)
	orderId, _ := strconv.ParseInt(v.OrderId, 10, 0)
	order, err := shopping.GetOrderById(orderId)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	var result string = ""
	var req = new(event.TradeMsg)
	req.CompanyId = order.PartnerId
	req.UserId = order.MemberId
	req.OrderId = orderId
	req.MsgHeader.EventType = v.Event
	message, err := event.EncodeMsg(req)
	if err != nil {
        this.ServeError(err.Error())
		return      
    }
	event.KernelBus.Publish(v.Event,message,&result)
	if len(result) > 0 {
		this.ServeError(result)
		return
	}
	rsp := struct {
		    OrderId   string      `json:"order_id"`
	        Modified  time.Time   `json:"modified"`
	    }{OrderId:v.OrderId, Modified:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}
//商家手工确认订单付款
func (this *OrdersController) SellerConfirmPay() {
	v := struct {
	    OrderId      string   `form:"order_id" valid:"Required"`
		Event        string   `form:"event" valid:"Required"`
	}{Event:"E_ORDER_CONFIRMPAYMENT" } 
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	//curPartnerId := this.Ctx.Input.GetData("curCompanyId").(int)
	orderId, _ := strconv.ParseInt(v.OrderId, 10, 0)
	order, err := shopping.GetOrderById(orderId)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	var result string = ""
	var req = new(event.TradeMsg)
	req.CompanyId = order.PartnerId
	req.UserId = order.MemberId
	req.OrderId = orderId
	req.MsgHeader.EventType = v.Event
	message, err := event.EncodeMsg(req)
	if err != nil {
        this.ServeError(err.Error())
		return      
    }
	event.KernelBus.Publish(v.Event,message,&result)
	if len(result) > 0 {
		this.ServeError(result)
		return
	}
	rsp := struct {
		    OrderId   string      `json:"order_id"`
	        Modified  time.Time   `json:"modified"`
	    }{OrderId:v.OrderId, Modified:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

//商家订单确认
func (this *OrdersController) SellerConfirm() {
	v := struct {
	    OrderId      string   `form:"order_id" valid:"Required"`
		Event        string   `form:"event" valid:"Required"`
	}{Event:"E_ORDER_CONFIRM" } 
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	curPartnerId := this.Ctx.Input.GetData("curCompanyId").(int)
	orderId, _ := strconv.ParseInt(v.OrderId, 10, 0)
	order, err := shopping.GetOrderById(orderId)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	var result string = ""
	var req = new(event.TradeMsg)
	req.CompanyId = order.PartnerId
	req.UserId = order.MemberId
	req.OrderId = orderId
	req.MsgHeader.EventType = v.Event
	message, err := event.EncodeMsg(req)
	if err != nil {
        this.ServeError(err.Error())
		return      
    }
	event.KernelBus.Publish(v.Event,message,&result)
	if len(result) > 0 {
		this.ServeError(result)
		return
	}
	orders, err := shopping.GetOrderById(orderId)
	if err != nil {
        this.ServeError(err.Error())
		return      
    }
    if orders.FlowType != 2 {
	    account, err := member.GetAccountById(int64(orders.MemberId))
		if err != nil {
			this.ServeError(err.Error())
			return
		}
		memberlayer.UpdateAccountForOrder(int64(curPartnerId),orders.MemberId,account,true,orders.Payment,1,1)	
	}			   
	rsp := struct {
		    OrderId   string      `json:"order_id"`
	        Modified  time.Time   `json:"modified"`
	    }{OrderId:v.OrderId, Modified:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

//商家订单发货
func (this *OrdersController) SellerDelivery() {
	v := struct {
	    OrderId      string   `form:"order_id" valid:"Required"`
		Event        string   `form:"event" valid:"Required"`
	}{Event:"E_ORDER_DELIVERY" } 
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	//curPartnerId := this.Ctx.Input.GetData("curCompanyId").(int)
	orderId, _ := strconv.ParseInt(v.OrderId, 10, 0)
	order, err := shopping.GetOrderById(orderId)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	var result string = ""
	var req = new(event.TradeMsg)
	req.CompanyId = order.PartnerId
	req.UserId = order.MemberId
	req.OrderId = orderId
	req.MsgHeader.EventType = v.Event
	message, err := event.EncodeMsg(req)
	if err != nil {
        this.ServeError(err.Error())
		return      
    }
	event.KernelBus.Publish(v.Event,message,&result)
	if len(result) > 0 {
		this.ServeError(result)
		return
	}
	rsp := struct {
		    OrderId   string      `json:"order_id"`
	        Modified  time.Time   `json:"modified"`
	    }{OrderId:v.OrderId, Modified:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

//买家订单评价
func (this *OrdersController) Rated() {
	v := struct {
	    OrderId      string   `form:"order_id" valid:"Required"`
		Event        string   `form:"event" valid:"Required"`
	}{Event:"E_ORDER_RATED" } 
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	//curUserId := this.Ctx.Input.GetData("curUserId").(int)
	orderId, _ := strconv.ParseInt(v.OrderId, 10, 0)
	order, err := shopping.GetOrderById(orderId)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	var result string = ""
	var req = new(event.TradeMsg)
	req.CompanyId = order.PartnerId
	req.UserId = order.MemberId
	req.OrderId = orderId
	req.MsgHeader.EventType = v.Event
	message, err := event.EncodeMsg(req)
	if err != nil {
        this.ServeError(err.Error())
		return      
    }
	event.KernelBus.Publish(v.Event,message,&result)
	if len(result) > 0 {
		this.ServeError(result)
		return
	}
	rsp := struct {
		    OrderId   string      `json:"order_id"`
	        Modified  time.Time   `json:"modified"`
	    }{OrderId:v.OrderId, Modified:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}
//买家发起售后
func (this *OrdersController) AfterService() {
	v := struct {
	    OrderId      string   `form:"order_id" valid:"Required"`
		Event        string   `form:"event" valid:"Required"`
	}{Event:"E_ORDER_SERVICE" } 
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	//curUserId := this.Ctx.Input.GetData("curUserId").(int)
	orderId, _ := strconv.ParseInt(v.OrderId, 10, 0)
	order, err := shopping.GetOrderById(orderId)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	var result string = ""
	var req = new(event.TradeMsg)
	req.CompanyId = order.PartnerId
	req.UserId = order.MemberId
	req.OrderId = orderId
	req.MsgHeader.EventType = v.Event
	message, err := event.EncodeMsg(req)
	if err != nil {
        this.ServeError(err.Error())
		return      
    }
	event.KernelBus.Publish(v.Event,message,&result)
	if len(result) > 0 {
		this.ServeError(result)
		return
	}
	rsp := struct {
		    OrderId   string      `json:"order_id"`
	        Modified  time.Time   `json:"modified"`
	    }{OrderId:v.OrderId, Modified:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}
//商家关闭订单
func (this *OrdersController) CloseOrder() {
	v := struct {
	    OrderId      string   `form:"order_id" valid:"Required"`
		Event        string   `form:"event" valid:"Required"`
	}{Event:"E_ORDER_CLOSE" } 
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	//curUserId := this.Ctx.Input.GetData("curUserId").(int)
	orderId, _ := strconv.ParseInt(v.OrderId, 10, 0)
	order, err := shopping.GetOrderById(orderId)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	var result string = ""
	var req = new(event.TradeMsg)
	req.CompanyId = order.PartnerId
	req.UserId = order.MemberId
	req.OrderId = orderId
	req.MsgHeader.EventType = v.Event
	message, err := event.EncodeMsg(req)
	if err != nil {
        this.ServeError(err.Error())
		return      
    }
	event.KernelBus.Publish(v.Event,message,&result)
	if len(result) > 0 {
		this.ServeError(result)
		return
	}
	rsp := struct {
		OrderId   string      `json:"order_id"`
	    Modified  time.Time   `json:"modified"`
	}{OrderId:v.OrderId, Modified:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

//订单手工拆分
func (this *OrdersController) Order2MultiOrders() {
	//curRoleId := this.Ctx.Input.GetData("curRoleId").(int) 
	//companyId := int64(this.Ctx.Input.GetData("curCompanyId").(int))
	curUserId := int64(this.Ctx.Input.GetData("curUserId").(int))
	if curUserId == 0 {
		this.ServeError("user is not login")
	    return
	}
	v := struct {
	    StoreId   int64    `form:"store_id"`
		OrderId   string   `form:"order_id"`
		GroupIds  string   `form:"group_ids"`
	}{}     
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	orderId, err := strconv.ParseInt(v.OrderId, 10, 64)
	if err != nil {
	    this.ServeError(err.Error())
		return	
	}
	orders, err := shopping.GetOrderById(orderId)
	if err != nil {
	    this.ServeError(err.Error())
		return	
	}
	beego.Debug(orders.OrderId)
	if len(v.GroupIds) > 2 {
	    for _, ids := range strings.Split(v.GroupIds, ";") {
			//创建新的订单
			splitOrder := new(shopping.ValueOrder)
			splitOrder.OrderId, _ = uuid.GetSnowFlakeId(uuid.Worker)
			shopping.AddOrder(splitOrder)
			for _, idStr := range strings.Split(ids, ","){
			  //更改子订单的所属新订单
			  id, _:= strconv.ParseInt(idStr, 10, 64)
			  shopping.UpdateOrderItemOrderId(id, splitOrder.OrderId)
			}
	    }
	}
	r := struct {
	    OrderIds []string `json:"order_ids"`
	}{}
	this.Data["json"] = r
	this.ServeJSON()
}
